﻿using Sunny.UI;
using System;
using System.Threading;

namespace Sunny.FrameDecoder.Demo
{
    internal class TestByteFrameDecoder
    {
        /// <summary>
        /// 测试固定长度解码器
        /// </summary>
        public static void TestFixedLengthFrameDecoder()
        {
            Console.WriteLine(Environment.NewLine + "TestFixedLengthFrameDecoder:");
            var decoder = new FixedLengthFrameDecoder(5);
            decoder.OnDecoder += Decoder_OnFixedLengthFrameDecoder;
            decoder.Decode(new byte[] { 1, 2, 3 });
            decoder.Decode(new byte[] { 4, 5, 1, 2 });
            decoder.Decode(new byte[] { 3, 4, 5, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 1, 2 });
            decoder.Decode(new byte[] { 3, 4, 5, 1, 2 });
            decoder.Decode(new byte[] { 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5 });
        }

        private static void Decoder_OnFixedLengthFrameDecoder(object sender, IByteEventArgs e)
        {
            if (e is FixedLengthByteFrameDataEventArgs a)
                Console.WriteLine(a.Value.ToHexString());
        }

        /// <summary>
        /// 测试分隔符(尾部分隔符)解码器
        /// </summary>
        public static void TestDelimiterBasedFrameDecoder()
        {
            Console.WriteLine(Environment.NewLine + "TestDelimiterBasedFrameDecoder:");
            var decoder = new DelimiterBasedFrameDecoder(new byte[] { 0xAA });
            decoder.OnDecoder += Decoder_OnDelimiterBasedFrameDecoder;
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3 });
            decoder.Decode(new byte[] { 4, 5, 0xAA, 1, 2 });
            decoder.Decode(new byte[] { 3, 4, 5, 0xAA, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3, 4, 5, 0xAA });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xAA });
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3, 4, 5, 0xAA, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3, 4, 5, 0xAA });
        }

        public static void Decoder_OnDelimiterBasedFrameDecoder(object sender, IByteEventArgs e)
        {
            if (e is DelimiterByteFrameDataEventArgs a)
            {
                Console.WriteLine(e.Value.ToHexString() + ", " + a.Body.ToHexString());
                if (a.Decoder is DelimiterBasedFrameDecoder d)
                {
                    if (d.DecodeFrame(a.Body, out var args))
                    {
                        ThrowHelper.ThrowIfNotEquel(args.Value, a.Value);
                    }
                    else
                    {
                        ThrowHelper.ThrowIfNull(args);
                    }
                }
            }
        }

        /// <summary>
        /// 测试头部分隔符解码器
        /// </summary>
        public static void TestHeaderDelimiterFrameDecoder()
        {
            Console.WriteLine(Environment.NewLine + "TestHeaderDelimiterFrameDecoder:");
            var decoder = new HeaderDelimiterFrameDecoder(new byte[] { 0xAA });
            decoder.OnDecoder += Decoder_OnHeaderDelimiterFrameDecoder; ;
            decoder.Decode(new byte[] { 1, 2, 3, 0xAA, 1, 2, 3 });
            decoder.Decode(new byte[] { 4, 5, 0xAA, 1, 2 });
            decoder.Decode(new byte[] { 3, 4, 5, 0xAA, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3, 4, 5, 0xAA });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xAA });
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3, 4, 5, 0xAA, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xAA, 1, 2, 3, 4, 5, 0xAA });
        }

        private static void Decoder_OnHeaderDelimiterFrameDecoder(object sender, IByteEventArgs e)
        {
            if (e is HeaderDelimiterByteFrameDataEventArgs a)
            {
                Console.WriteLine(e.Value.ToHexString() + ", " + a.Body.ToHexString());
                if (a.Decoder is HeaderDelimiterFrameDecoder d)
                {
                    if (d.DecodeFrame(a.Body, out var args))
                    {
                        ThrowHelper.ThrowIfNotEquel(args.Value, a.Value);
                    }
                    else
                    {
                        ThrowHelper.ThrowIfNull(args);
                    }
                }
            }
        }

        /// <summary>
        /// 测试头部尾部分隔符解码器
        /// </summary>
        public static void TestHeaderTailFrameDecoder()
        {
            Console.WriteLine(Environment.NewLine + "TestHeaderTailFrameDecoder:");
            var decoder = new HeaderTailFrameDecoder(new byte[] { 0xAA }, new byte[] { 0xBB });
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnHeaderTailFrameDecoder; ;
            decoder.Decode(new byte[] { 3, 4, 5, 0xAA, 1, 2, 3 });
            decoder.Decode(new byte[] { 4, 5, 0xBB, 1, 0xAA, 1, 2 });
            decoder.Decode(new byte[] { 3, 4, 5, 0xBB, 1, 2, 0xAA, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 1, 2, 3, 4, 5, 0xBB, 0xAA, 0xAA, });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xBB });
            decoder.Decode(new byte[] { 0xAA, 0xBB });
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3, 4, 5, 0xBB, 0xAA, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xAA, 1, 2, 3, 4, 5, 0xBB });
        }

        private static void Decoder_OnHeaderTailFrameDecoder(object sender, IByteEventArgs e)
        {
            if (e is ByteFrameDataEventArgs a)
            {
                Console.WriteLine(e.Value.ToHexString() + ", " + a.Body.ToHexString());

                if (a.Decoder is HeaderTailFrameDecoder decoder)
                {
                    if (decoder.DecodeFrame(a.Body, out var args))
                    {
                        ThrowHelper.ThrowIfNotEquel(args.Value, a.Value);
                    }
                    else
                    {
                        ThrowHelper.ThrowIfNull(args);
                    }
                }
            }
        }

        /// <summary>
        /// 测试LengthValue解码器
        /// </summary>
        public static void TestLengthValueFrameDecoder()
        {
            Console.WriteLine(Environment.NewLine + "TestLengthValueFrameDecoder:");
            var decoder = new LengthValueFrameDecoder(ValueLengthType.Byte);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnLengthValueFrameDecoder;
            decoder.Decode(new byte[] { 3, 1, 2, 3, 1, 1, 0 });
            decoder.Decode(new byte[] { 4, 1, 2, 3, 4, 5, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 2, 1, 2, 5, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 5, 1, 2, 3, 4, 5, 1, 1, 0, 5 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 3 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 5, 1, 2, 3, 4, 5, 5, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 5, 1, 2, 3, 4, 5 });

            Console.WriteLine(Environment.NewLine + "TestLengthValueFrameDecoder:");
            decoder = new LengthValueFrameDecoder(ValueLengthType.Byte, true, true);
            decoder.OnDecoder += Decoder_OnLengthValueFrameDecoder;
            decoder.Decode(new byte[] { 4, 1, 2, 3, 2, 1, 1 });
            decoder.Decode(new byte[] { 5, 1, 2, 3, 4, 6, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 3, 1, 2, 6, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 6, 1, 2, 3, 4, 5, 2, 1, 1, 6 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 4 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 6, 1, 2, 3, 4, 5 });
        }

        public static void Decoder_OnLengthValueFrameDecoder(object sender, IByteEventArgs e)
        {
            if (e is LengthValueFrameDataEventArgs a)
            {
                Console.WriteLine(a.Length + ": " + e.Value.ToHexString() + ", " + a.Body.ToHexString());

                if (a.Decoder is LengthValueFrameDecoder decoder)
                {
                    if (decoder.DecodeFrame(a.Body, out var args))
                    {
                        ThrowHelper.ThrowIfNotEquel(args.Value, a.Value);
                    }
                    else
                    {
                        ThrowHelper.ThrowIfNull(args);
                    }
                }
            }
        }

        /// <summary>
        /// 测试TagLengthValue解码器
        /// </summary>
        public static void TestTagLengthValueFrameDecoder()
        {
            Console.WriteLine(Environment.NewLine + "TestTagLengthValueFrameDecoder:");
            var decoder = new TagLengthValueFrameDecoder(1, ValueLengthType.Byte);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnTagLengthValueFrameDecoder;
            decoder.Decode(new byte[] { 0xA3, 3, 1, 2, 3, 0xA1, 1, 1, 0xA0, 0 });
            decoder.Decode(new byte[] { 0xA4, 4, 1, 2, 3, 4, 0xA5, 5, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 0xA2, 2, 1, 2, 0xA5, 5, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xA5, 5, 1, 2, 3, 4, 5, 0xA1, 1, 1, 0xA0, 0, 0xA5, 5 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xA3, 3 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 0xA5, 5, 1, 2, 3, 4, 5, 0xA5, 5, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xA5, 5, 1, 2, 3, 4, 5 });

            Console.WriteLine(Environment.NewLine + "TestTagLengthValueFrameDecoder: isFullLength = true");
            decoder = new TagLengthValueFrameDecoder(1, ValueLengthType.Byte, true, true);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnTagLengthValueFrameDecoder;
            decoder.Decode(new byte[] { 0xA3, 5, 1, 2, 3, 0xA1, 3, 1, 0xA0, 2 });
            decoder.Decode(new byte[] { 0xA4, 6, 1, 2, 3, 4, 0xA5, 7, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 0xA2, 4, 1, 2, 0xA5, 7, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xA5, 7, 1, 2, 3, 4, 5, 0xA1, 3, 1, 0xA0, 2, 0xA5, 7 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xA3, 5 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 0xA5, 7, 1, 2, 3, 4, 5, 0xA5, 7, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xA5, 7, 1, 2, 3, 4, 5 });

            Console.WriteLine(Environment.NewLine + "TestTagLengthValueFrameDecoder: tagLength = 0");
            decoder = new TagLengthValueFrameDecoder(0, ValueLengthType.Byte);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnTagLengthValueFrameDecoder;
            decoder.Decode(new byte[] { 3, 1, 2, 3, 1, 1, 0 });
            decoder.Decode(new byte[] { 4, 1, 2, 3, 4, 5, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 2, 1, 2, 5, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 5, 1, 2, 3, 4, 5, 1, 1, 0, 5 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 3 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 5, 1, 2, 3, 4, 5, 5, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 5, 1, 2, 3, 4, 5 });
        }

        private static void Decoder_OnTagLengthValueFrameDecoder(object sender, IByteEventArgs e)
        {
            if (e is TagLengthValueFrameDataEventArgs a)
            {
                Console.WriteLine(a.Tag.ToHexString() + ": " + a.Length + ": " + e.Value.ToHexString() + ", " + a.Body.ToHexString());

                if (a.Decoder is TagLengthValueFrameDecoder decoder)
                {
                    if (decoder.DecodeFrame(a.Body, out var args))
                    {
                        ThrowHelper.ThrowIfNotEquel(args.Value, a.Value);
                    }
                    else
                    {
                        ThrowHelper.ThrowIfNull(args);
                    }
                }
            }
        }

        /// <summary>
        /// 测试TagLengthValue解码器
        /// </summary>
        public static void TestHeaderTagLengthValueTailFrameDecoder()
        {
            Console.WriteLine(Environment.NewLine + "TestHeaderTagLengthValueTailFrameDecoder:");
            var decoder = new HeaderTagLengthValueTailFrameDecoder(new byte[] { 0xAA }, new byte[] { 0xBB }, 1, ValueLengthType.Byte);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnHeaderTagLengthValueTailFrameDecoder;
            decoder.Decode(new byte[] { 0xAA, 0xA3, 3, 1, 2, 3, 0xBB, 0xAA, 0xA1, 1, 1, 0xBB, 0xAA, 0xA0, 0 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 0xA4, 4, 1, 2, 3, 4, 0xBB, 0xAA, 0xA5, 5, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 0xBB, 0xAA, 0xA2, 2, 1, 2, 0xBB, 0xAA, 0xA5, 5, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 0xA5, 5, 1, 2, 3, 4, 5, 0xBB, 0xAA, 0xA1, 1, 1, 0xBB, 0xAA, 0xA0, 0, 0xBB, 0xAA, 0xA5, 5 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xBB, 0xAA, 0xA3, 3 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 0xBB, 0xAA, 0xA5, 5, 1, 2, 3, 4, 5, 0xBB, 0xAA, 0xA5, 5, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xAA, 0xA5, 5, 1, 2, 3, 4, 5, 0xBB });

            Console.WriteLine(Environment.NewLine + "TestHeaderTagLengthValueTailFrameDecoder: isFullLength = true");
            decoder = new HeaderTagLengthValueTailFrameDecoder(new byte[] { 0xAA }, new byte[] { 0xBB }, 1, ValueLengthType.Byte, true, true);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnHeaderTagLengthValueTailFrameDecoder;
            decoder.Decode(new byte[] { 0xAA, 0xA3, 7, 1, 2, 3, 0xBB, 0xAA, 0xA1, 5, 1, 0xBB, 0xAA, 0xA0, 4 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 0xA4, 8, 1, 2, 3, 4, 0xBB, 0xAA, 0xA5, 9, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 0xBB, 0xAA, 0xA2, 6, 1, 2, 0xBB, 0xAA, 0xA5, 9, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 0xA5, 9, 1, 2, 3, 4, 5, 0xBB, 0xAA, 0xA1, 5, 1, 0xBB, 0xAA, 0xA0, 4, 0xBB, 0xAA, 0xA5, 9 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xBB, 0xAA, 0xA3, 7 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 0xBB, 0xAA, 0xA5, 9, 1, 2, 3, 4, 5, 0xBB, 0xAA, 0xA5, 9, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xAA, 0xA5, 9, 1, 2, 3, 4, 5, 0xBB });

            Console.WriteLine(Environment.NewLine + "TestHeaderTagLengthValueTailFrameDecoder: tagLength = 0");
            decoder = new HeaderTagLengthValueTailFrameDecoder(new byte[] { 0xAA }, new byte[] { 0xBB }, 0, ValueLengthType.Byte);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnHeaderTagLengthValueTailFrameDecoder;
            decoder.Decode(new byte[] { 0xAA, 3, 1, 2, 3, 0xBB, 0xAA, 1, 1, 0xBB, 0xAA, 0 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 4, 1, 2, 3, 4, 0xBB, 0xAA, 5, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 0xBB, 0xAA, 2, 1, 2, 0xBB, 0xAA, 5, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 5, 1, 2, 3, 4, 5, 0xBB, 0xAA, 1, 1, 0xBB, 0xAA, 0, 0xBB, 0xAA, 5 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xBB, 0xAA, 3 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 0xBB, 0xAA, 5, 1, 2, 3, 4, 5, 0xBB, 0xAA, 5, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xAA, 5, 1, 2, 3, 4, 5, 0xBB });

            Console.WriteLine(Environment.NewLine + "TestHeaderTagLengthValueTailFrameDecoder: isFullLength = true，tagLength = 0");
            decoder = new HeaderTagLengthValueTailFrameDecoder(new byte[] { 0xAA }, new byte[] { 0xBB }, 0, ValueLengthType.Byte, true, true);
            //decoder.CacheTimeout = 0;
            decoder.OnDecoder += Decoder_OnHeaderTagLengthValueTailFrameDecoder;
            decoder.Decode(new byte[] { 0xAA, 6, 1, 2, 3, 0xBB, 0xAA, 4, 1, 0xBB, 0xAA, 3 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 7, 1, 2, 3, 4, 0xBB, 0xAA, 8, 1 });
            decoder.Decode(new byte[] { 2, 3, 4, 5, 0xBB, 0xAA, 5, 1, 2, 0xBB, 0xAA, 8, 1, 2, 3, 4, 5 });
            decoder.Decode(new byte[] { 0xBB, 0xAA, 8, 1, 2, 3, 4, 5, 0xBB, 0xAA, 4, 1, 0xBB, 0xAA, 3, 0xBB, 0xAA, 8 });
            decoder.Decode(new byte[] { 1, 2, 3, 4, 5, 0xBB, 0xAA, 6 });
            decoder.Decode(new byte[] { 1, 2 });
            decoder.Decode(new byte[] { 3, 0xBB, 0xAA, 8, 1, 2, 3, 4, 5, 0xBB, 0xAA, 8, 1, 2, 3 });
            Thread.Sleep(1000);
            decoder.Decode(new byte[] { 0xAA, 8, 1, 2, 3, 4, 5, 0xBB });
        }

        public static void Decoder_OnHeaderTagLengthValueTailFrameDecoder(object sender, IByteEventArgs e)
        {
            if (e is HeaderTagLengthValueTailFrameDataEventArgs a)
            {
                Console.WriteLine(a.Tag.ToHexString() + ": " + a.Length + ": " + e.Value.ToHexString() + ", " + a.Body.ToHexString());

                if (a.Decoder is HeaderTagLengthValueTailFrameDecoder decoder)
                {
                    if (decoder.DecodeFrame(a.Body, out var args))
                    {
                        ThrowHelper.ThrowIfNotEquel(args.Value, a.Value);
                    }
                    else
                    {
                        ThrowHelper.ThrowIfNull(args);
                    }
                }
            }
        }

        public static void TestCreateFrame()
        {
            byte[] bts = new byte[] { 1, 2, 3, 0xFF, 0xFB };
            var decoder1 = new DelimiterBasedFrameDecoder(new byte[] { 0xFF, 0xFB });
            decoder1.OnDecoder += DelimiterBasedFrameDecoder_OnDecoder;
            decoder1.Decode(bts);

            bts = new byte[] { 0xFF, 0xFB, 1, 2, 3 };
            var decoder2 = new HeaderDelimiterFrameDecoder(new byte[] { 0xFF, 0xFB });
            decoder2.OnDecoder += HeaderDelimiterFrameDecoder_OnDecoder;
            decoder2.Decode(bts);
            decoder2.Decode(bts);

            bts = new byte[] { 0xFF, 0xFB, 0xAA, 2, 3, 4, 0xF7, 0xF7 };
            var decoder3 = new HeaderTagLengthValueTailFrameDecoder(new byte[] { 0xFF, 0xFB }, new byte[] { 0xF7, 0xF7 }, 1, ValueLengthType.Byte);
            decoder3.OnDecoder += HeaderTagLengthValueTailFrameDecoder_OnDecoder;
            decoder3.Decode(bts);

            bts = new byte[] { 0xFF, 0xFB, 0xAA, 2, 3, 4, 0xF7, 0xF7 };
            var decoder4 = new HeaderTailFrameDecoder(new byte[] { 0xFF, 0xFB }, new byte[] { 0xF7, 0xF7 });
            decoder4.OnDecoder += HeaderTailFrameDecoder_OnDecoder;
            decoder4.Decode(bts);

            bts = new byte[] { 2, 3, 4 };
            var decoder5 = new LengthValueFrameDecoder(ValueLengthType.Byte);
            decoder5.OnDecoder += LengthValueFrameDecoder_OnDecoder;
            decoder5.Decode(bts);

            bts = new byte[] { 0xAA, 2, 3, 4 };
            var decoder6 = new TagLengthValueFrameDecoder(1, ValueLengthType.Byte);
            decoder6.OnDecoder += TagLengthValueFrameDecoder_OnDecoder;
            decoder6.Decode(bts);

        }

        private static void DelimiterBasedFrameDecoder_OnDecoder(object sender, IByteEventArgs e)
        {
            var bts = new byte[5] { 1, 2, 3, 0xFF, 0xFB };
            var decoder = (DelimiterBasedFrameDecoder)e.Decoder;
            Console.WriteLine("DelimiterBasedFrameDecoder: " + decoder.CreateFrame(e.Value).AsSpan().SequenceEqual(bts.AsSpan()));
        }

        private static void HeaderDelimiterFrameDecoder_OnDecoder(object sender, IByteEventArgs e)
        {
            var bts = new byte[5] { 0xFF, 0xFB, 1, 2, 3 };
            var decoder = (HeaderDelimiterFrameDecoder)e.Decoder;
            Console.WriteLine("HeaderDelimiterFrameDecoder: " + decoder.CreateFrame(e.Value).AsSpan().SequenceEqual(bts.AsSpan()));
        }

        private static void HeaderTagLengthValueTailFrameDecoder_OnDecoder(object sender, IByteEventArgs e)
        {
            var bts = new byte[] { 0xFF, 0xFB, 0xAA, 2, 3, 4, 0xF7, 0xF7 };
            var decoder = (HeaderTagLengthValueTailFrameDecoder)e.Decoder;
            var args = (TagLengthValueFrameDataEventArgs)e;
            Console.WriteLine("HeaderTagLengthValueTailFrameDecoder: " + decoder.CreateFrame(args.Tag, e.Value).AsSpan().SequenceEqual(bts.AsSpan()));
        }

        private static void HeaderTailFrameDecoder_OnDecoder(object sender, IByteEventArgs e)
        {
            var bts = new byte[] { 0xFF, 0xFB, 0xAA, 2, 3, 4, 0xF7, 0xF7 };
            var decoder = (HeaderTailFrameDecoder)e.Decoder;
            Console.WriteLine("HeaderTailFrameDecoder: " + decoder.CreateFrame(e.Value).AsSpan().SequenceEqual(bts.AsSpan()));
        }

        private static void LengthValueFrameDecoder_OnDecoder(object sender, IByteEventArgs e)
        {
            var bts = new byte[] { 2, 3, 4 };
            var decoder = (LengthValueFrameDecoder)e.Decoder;
            Console.WriteLine("LengthValueFrameDecoder: " + decoder.CreateFrame(e.Value).AsSpan().SequenceEqual(bts.AsSpan()));
        }

        private static void TagLengthValueFrameDecoder_OnDecoder(object sender, IByteEventArgs e)
        {
            var bts = new byte[] { 0xAA, 2, 3, 4 };
            var decoder = (TagLengthValueFrameDecoder)e.Decoder;
            var args = (TagLengthValueFrameDataEventArgs)e;
            Console.WriteLine("TagLengthValueFrameDecoder: " + decoder.CreateFrame(args.Tag, e.Value).AsSpan().SequenceEqual(bts.AsSpan()));
        }
    }
}
